package com.test;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;

public class Packing{
	public static void main(String[] args){
		System.out.println("22==");
		new Packing().show();
	}
	
	Color[] colors = new Color[]{ 
			Color.GREEN, Color.RED, Color.BLUE, Color.YELLOW, 
			Color.CYAN, Color.GRAY, Color.ORANGE, Color.BLACK};
	
	void show(){
		JFrame frame = new JFrame("puzzle");
		frame.setSize(500,550);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		JTable table = new JTable(8,8);
		table.setRowHeight(60);
		table.setDefaultRenderer(Object.class, new MyRenderer());

		frame.setLayout(new BorderLayout());
		frame.add(table);

		Figures figures = new Figures();
		for( int i=0; i<250000; i++ ){
		  System.out.println("attempt #"+i);
		  clear(table);
		  figures.shuffle();
		  if( placeFigures(table, figures) ){
			  break;
		  }
		}
		
		//table.setValueAt(Color.RED,0,0);
		//table.setValueAt(Color.BLUE,4,0);
		
		frame.setVisible(true);
	}
	
	void clear(JTable table){
		for( int x=0; x<table.getColumnCount(); x++ ){
			for( int y=0; y<table.getRowCount(); y++ ){
				table.setValueAt(null, y, x);
			}
		}
	}

	boolean placeFigures(JTable table, Figures figures) {
		for( int i=0; i<figures.size(); i++ ){
			//System.out.println("figures "+i);
			Figure fig = figures.randomRotation(i);
			tablePos:
			for( int x=0; x<table.getColumnCount(); x++ ){
				for( int y=0; y<table.getRowCount(); y++ ){
					//System.out.println("val="+table.getValueAt(y, x));
					if( table.getValueAt(y, x)==null ){
						boolean ok = fig.draw(table, colors[i], x, y);
						//System.out.println("draw ok = "+ok + " at x,y="+x+","+y);
						if( !ok ){
							return false;
						}
						break tablePos;
					}
				}
			}
		}
		return true;
	}
	
	
	
	class Figure{
		List<List<Long>> points = new ArrayList();
		void addLine(String line){
			List<Long> row = new ArrayList();
			points.add(row);
			for( int i=0; i<line.length(); i++ ){
				if( line.charAt(i)=='*' ){
					row.add((long)i);
				}
			}
		}
		boolean draw(JTable tab, Color color, int x, int y){
			for( int i=0; i<points.size(); i++ ){
				for( long j : points.get(i) ){
					if( x+j<tab.getColumnCount() && y+i<tab.getRowCount() &&
							tab.getValueAt((int)(y+i), (int)(x+j))==null){
						// ok
					}else{
						return false;
					}
				}
			}

			for( int i=0; i<points.size(); i++ ){
				for( long j : points.get(i) ){
					tab.setValueAt(color, (int)(y+i), (int)(x+j));
				}
			}
			return true;
		}
	}
	
	class Figures{
		List<List<Figure>> figs = new ArrayList();
		Figures(){
			InputStream in = this.getClass().getClassLoader().getResourceAsStream("figures.txt");
			try{
		      BufferedReader br = new BufferedReader(new InputStreamReader(in));
		      String line="";
		      for(;;){
			      List<Figure> rotations = new ArrayList();
			      System.out.println("new figure");
			      figs.add(rotations);
			      for(;;){
				      Figure f = new Figure();
				      System.out.println("new rotation");
				      rotations.add(f);
				      while((line=br.readLine().trim()).charAt(0)!='-'){
				    	  f.addLine(line);
				      }
				      if( line.length()>1 ){
				    	  break;
				      }
			      }
			      if( line.charAt(1)=='0' ){
			    	  break;
			      }
		      }
			}catch(IOException e){
				throw new RuntimeException(e);
			}
		}
		int size(){
			return figs.size();
		}
		Figure randomRotation(int figure){
			List<Figure> list = figs.get(figure);
			return list.get((int)(Math.random()*list.size()));
		}
		void shuffle(){
			Collections.shuffle(figs);
		}
	}
	
	static class MyRenderer extends DefaultTableCellRenderer {

        @Override
        public Component getTableCellRendererComponent(
              JTable table, Object value, boolean isSelected,
              boolean hasFocus, int row, int column) {
            JLabel c = (JLabel)super.getTableCellRendererComponent(
                table, value, isSelected, hasFocus, row, column);
            c.setText("");
            c.setOpaque(true);
            c.setBackground((Color)value);
            //System.out.println(""+row);
            return c;
        }
    }
}